package com.sqlhandle;

import com.lcx.annotation.HandCoreInit;
import com.lcx.annotation.IOCValue;
import com.lcx.annotation.JsObject;
import com.lcx.core.HandleCore;
import com.lcx.core.Scanner;
import com.me.common.ToolsList;
import com.me.util.FileUtils;
import com.sql.api.HtmlRunnerApi;
import com.sql.common.intc.SqlTypeConvert;
import com.sql.common.intc.impl.DefaultTimeConvert;
import com.sql.common.util.ConnectionFactory;
import com.sql.common.util.PropertyUtil;

import java.sql.Types;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@IOCValue
@JsObject(name = "sqlUtil",value = "sqlShell.html")
public class SqlHandleUtil {

    private static final Map<Integer,SqlTypeConvert> convert = new HashMap<>();

    private PropertyUtil propertyUtil;

    private String configPath = "config.properties";

    private String codePath = "functionCode.dat";

    private ConnectionFactory connectionFactory;

    private HtmlRunnerApi htmlRunnerApi;

    private Map<String,String> functionCode = new HashMap<>();

    static {
        SqlTypeConvert c = new DefaultTimeConvert();
        convert.put(Types.DATE,c);
        convert.put(Types.TIMESTAMP,c);
    }

    {
        propertyUtil = new PropertyUtil(configPath);
        connectionFactory = new ConnectionFactory();
        htmlRunnerApi = new HtmlRunnerApi(null);
    }

    @JsObject
    public void setConfigPath(String path){
        propertyUtil.setConfigFilePath(path);
        this.configPath = path;
    }

    @JsObject
    public String getConfigFileName(){
        String str=configPath;
        int index;
        if((index=str.lastIndexOf("/"))>-1){
            str = str.substring(index+1);
        }
        if((index=str.lastIndexOf("."))>-1){
            str = str.substring(0,index);
        }
        return str;
    }

    @JsObject
    public void reloadProperty(){
        propertyUtil.loadProperty();
        connectionFactory.close();
    }

    @JsObject
    public void saveFunctionCode(Map<String,String> param){
        functionCode.clear();
        if(param != null){
            param.entrySet().stream().forEach(e->functionCode.put(e.getKey(),e.getValue()));
        }
        FileUtils.saveObject(functionCode,codePath);
    }

    @JsObject
    public Map<String,String> readFunctionCode(){
        Map<String,String> code = (Map<String, String>) FileUtils.readObject(codePath);
        if(code!=null && !code.isEmpty()){
            code.entrySet().stream().forEach(e->functionCode.put(e.getKey(),e.getValue()));
        }
        return functionCode;
    }

    @JsObject
    public void putConnectionInfo(Map<String,String> param){
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_FILE_NAME,param.get(ConnectionFactory.CONNECTION_FILE_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_DRIVER_CLASS_NAME,param.get(ConnectionFactory.CONNECTION_DRIVER_CLASS_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_USER_NAME,param.get(ConnectionFactory.CONNECTION_USER_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_PASSWORD_NAME,param.get(ConnectionFactory.CONNECTION_PASSWORD_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_URL_NAME,param.get(ConnectionFactory.CONNECTION_URL_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_SSH_HOST_NAME,param.get(ConnectionFactory.CONNECTION_SSH_HOST_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_SSH_PORT_NAME,param.get(ConnectionFactory.CONNECTION_SSH_PORT_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_SSH_USER_NAME,param.get(ConnectionFactory.CONNECTION_SSH_USER_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_SSH_PASSWORD_NAME,param.get(ConnectionFactory.CONNECTION_SSH_PASSWORD_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_PROXY_HOST_NAME,param.get(ConnectionFactory.CONNECTION_PROXY_HOST_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_PROXY_PORT_NAME,param.get(ConnectionFactory.CONNECTION_PROXY_PORT_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_TARGET_HOST_NAME,param.get(ConnectionFactory.CONNECTION_TARGET_HOST_NAME));
        propertyUtil.putProperty(ConnectionFactory.CONNECTION_TARGET_PORT_NAME,param.get(ConnectionFactory.CONNECTION_TARGET_PORT_NAME));
        connectionFactory.close();
        propertyUtil.saveProperty();
    }

    @JsObject
    public Object getConnectionProperty(){
        Map<String,Object> param = new HashMap<>();
        param.put(ConnectionFactory.CONNECTION_FILE_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_FILE_NAME));
        param.put(ConnectionFactory.CONNECTION_DRIVER_CLASS_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_DRIVER_CLASS_NAME));
        param.put(ConnectionFactory.CONNECTION_USER_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_USER_NAME));
        param.put(ConnectionFactory.CONNECTION_PASSWORD_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_PASSWORD_NAME));
        param.put(ConnectionFactory.CONNECTION_URL_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_URL_NAME));
        param.put(ConnectionFactory.CONNECTION_SSH_HOST_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_SSH_HOST_NAME));
        param.put(ConnectionFactory.CONNECTION_SSH_PORT_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_SSH_PORT_NAME));
        param.put(ConnectionFactory.CONNECTION_SSH_USER_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_SSH_USER_NAME));
        param.put(ConnectionFactory.CONNECTION_SSH_PASSWORD_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_SSH_PASSWORD_NAME));
        param.put(ConnectionFactory.CONNECTION_PROXY_HOST_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_PROXY_HOST_NAME));
        param.put(ConnectionFactory.CONNECTION_PROXY_PORT_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_PROXY_PORT_NAME));
        param.put(ConnectionFactory.CONNECTION_TARGET_HOST_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_TARGET_HOST_NAME));
        param.put(ConnectionFactory.CONNECTION_TARGET_PORT_NAME,propertyUtil.getProperty(ConnectionFactory.CONNECTION_TARGET_PORT_NAME));
        return param;
    }


    @JsObject
    public Object execSql(String sql,List<Object> param,Boolean isConvert) throws Exception{
        connectionFactory.getConnection(propertyUtil);
        htmlRunnerApi.setConnectionFactory(connectionFactory);
        Object obj= htmlRunnerApi.execSql(sql,param==null||param.isEmpty()?null:param.toArray(),isConvert==null||!isConvert?null:convert);
        return obj;
    }

    @JsObject(sync = false)
    public void testConnection(){
        connectionFactory.getConnection(propertyUtil);
    }

    @JsObject
    public void commit() throws Exception{
        connectionFactory.commit();
    }

    @JsObject
    public void rollback() throws Exception{
        connectionFactory.rollback();
    }

    @JsObject
    public void disConnection(){
        connectionFactory.close();
    }


    @HandCoreInit
    public void add(HandleCore handleCore){
        handleCore.getOnClosingEvent().add("SQL_UTIL",()->{
            disConnection();
        });
        ToolsList.addTools(new ToolsList.Tools("_sqlHandle","sql脚本","sql_shell/sqlShell.html","","版本：v1.0<br>powerd by Shisan.<br>说明：使用JS执行sql脚本，方便对数据库的批量操作。"),SqlHandleUtil.class);
    }
}
